#ifndef AV_PKT_BUF_H
#define AV_PKT_BUF_H
#include <stddef.h>
#include <stdint.h>
typedef struct av_pkt_buf_s av_pkt_buf_t;
typedef struct av_pkt_buf_desc_s av_pkt_buf_desc_t;
typedef struct av_pkt_buf_manager_s av_pkt_buf_manager_t;

struct av_pkt_buf_manager_s {
    av_pkt_buf_desc_t *desc;
    void *priv;
};

struct av_pkt_buf_s {
    // public read only
    size_t data_len;
    char *data;

    // bellow is private
    av_pkt_buf_manager_t *m;
};

/*! \enum av_pkt_buf_type_e
 *
 *  Detailed description
 */
typedef enum av_pkt_buf_type_e {
    AV_PKT_BUF_TYPE_ZEROTIME_HI3516,
    AV_PKT_BUF_TYPE_MAX,
} av_pkt_buf_type_t;

typedef av_pkt_buf_manager_t *(*av_pkt_buf_sys_init_func_t)(
    av_pkt_buf_desc_t *t);
typedef struct av_pkt_buf_s *(*av_pkt_buf_alloc_func_t)(
    av_pkt_buf_manager_t *m);
typedef void (*av_pkt_buf_free_func_t)(av_pkt_buf_t *buf);
typedef int (*av_pkt_buf_add_data_func_t)(av_pkt_buf_t *buf, char *data,
                                          size_t len);
typedef char *(*av_pkt_buf_data_func_t)(av_pkt_buf_t *buf);
typedef size_t (*av_pkt_buf_data_len_func_t)(av_pkt_buf_t *buf);
typedef void (*av_pkt_buf_set_data_len_func_t)(av_pkt_buf_t *buf, size_t);
typedef int (*av_pkt_buf_is_sof_func_t)(av_pkt_buf_t *buf);
typedef int (*av_pkt_buf_is_eof_func_t)(av_pkt_buf_t *buf);
typedef uint16_t (*av_pkt_buf_grp_func_t)(av_pkt_buf_t *buf);
typedef uint32_t (*av_pkt_buf_seq_func_t)(av_pkt_buf_t *buf);

struct av_pkt_buf_desc_s {
    uint8_t type;
    size_t priv_size;
    size_t max_pkt_len;
    av_pkt_buf_sys_init_func_t init_func;
    av_pkt_buf_alloc_func_t alloc_func;
    av_pkt_buf_free_func_t free_func;
    av_pkt_buf_add_data_func_t add_data_func;
    av_pkt_buf_data_func_t data_func;
    av_pkt_buf_data_len_func_t data_len_func;
    av_pkt_buf_set_data_len_func_t set_data_len_func;
    av_pkt_buf_is_sof_func_t is_sof_func;
    av_pkt_buf_is_eof_func_t is_eof_func;
    av_pkt_buf_grp_func_t grp_func;
    av_pkt_buf_seq_func_t seq_func;
};

av_pkt_buf_manager_t *av_pkt_buf_alloc_manager(av_pkt_buf_type_t type);
av_pkt_buf_t *av_pkt_buf_alloc(av_pkt_buf_manager_t *m);
void av_pkt_buf_free(av_pkt_buf_t *buf);
int av_pkt_buf_add_data(av_pkt_buf_t *buf, char *d, size_t l);
char *av_pkt_buf_data(av_pkt_buf_t *buf);
size_t av_pkt_buf_data_len(av_pkt_buf_t *buf);
void av_pkt_buf_set_data_len(av_pkt_buf_t *buf, size_t len);
// av_pkt_buf_hdr_t* av_pkt_buf_hdr(av_pkt_buf_t *buf);
size_t av_pkt_buf_hdr_len(av_pkt_buf_t *buf);
/*
t* If `buf` is the first pakcet of one frame, return 1, else 0
 */
int av_pkt_buf_is_sof(av_pkt_buf_t *buf);
/*
 * If `buf` is the last pakcet of one frame, return 1, else 0
 */
int av_pkt_buf_is_eof(av_pkt_buf_t *buf);

uint16_t av_pkt_buf_grp(av_pkt_buf_t *buf);
uint32_t av_pkt_buf_seq(av_pkt_buf_t *buf);
#endif /* ifndef AV_PKT_BUF_H */
